home *** CD-ROM | disk | FTP | other *** search
/ Aminet 40 / Aminet 40 (2000)(Schatztruhe)[!][Dec 2000].iso / Aminet / gfx / 3d / Skulpt_src.lha / sKulpt-src / 3DWProc.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2000-10-05  |  22.6 KB  |  562 lines

  1. #define STRICT
  2.  
  3. // Includes standard Windows
  4. #include <windows.h>
  5. #include <windowsx.h>
  6. #include <time.h>
  7. #include <stdlib.h>
  8. #include <malloc.h>
  9. #include <memory.h>
  10. #include <stdio.h>
  11.  
  12. // Includes D3D
  13. #define  D3D_OVERLOADS
  14. #include <ddraw.h>
  15. #include <d3d.h>
  16.  
  17. // Includes utilitaires D3D
  18. #include "d3dmath.h"
  19. #include "d3dutil.h"
  20. #include "D3DEnum.h"
  21.  
  22. #include <d3dx.h>
  23.  
  24. // Ids Resources
  25. //#include "resource.h"
  26.  
  27. // Constantes
  28. #include "const.h"
  29.  
  30. // Types
  31. #include "types.h"
  32.  
  33. // Variables globales projet
  34. #include "vars.h"
  35.  
  36. // Prototypes fonctions autres modules
  37. #include "proto.h"
  38.  
  39. // Macros
  40. #include "macros.h"
  41.  
  42. #define XDC_CLIPPINGDIST    (4.f)
  43.  
  44. static W3D_Context *hW3DC_3D;                               // Contexte Warp3D associé à la fenêtre 3D
  45. static HBITMAP hbDBuf_3D;                                   // Bitmap offscreen du double buffer
  46. static DC dcDBuf_3D, *hdcDBuf_3D = &dcDBuf_3D;              // RastPort du double buffer
  47. static bZBuf = FALSE;                                       // TRUE si on est arrivé à allouer le ZBuf dans le contexte W3D, FALSE sinon
  48. static int iWidth, iHeight;                                 // Mémoire largeur / hauteur pour ne rien faire si NEWSIZE avec mêmes dimensions
  49. static long lError;
  50. static BOOL bImage;                                         // TRUE si une image est OK dans le double buffer, FALSE sinon
  51. static W3D_Triangle sTriangle;
  52. static W3D_Double dZdepth = 1.;
  53. static W3D_Float fLeftEdge, fTopEdge, fW, fH, fXMed, fYMed;
  54. static int iLeftEdge, iTopEdge, iW, iH;
  55. static W3D_Vertex sV[4];
  56. static W3D_Triangles sTs; 
  57. static W3D_Color sC = {0., 0., 0., 1.};
  58. static W3D_Lines sLs;
  59. static W3D_Point sP;
  60.  
  61. static inline void vShow3DFrame(void)
  62. {
  63.     if (!bImage) return;
  64.  
  65.     ClipBlit(hdcDBuf_3D, iLeftEdge, iTopEdge, hWndPersp -> RPort, iLeftEdge, iTopEdge, iW, iH, 0xc0);
  66. }
  67.  
  68. // Versions plus rapides que celle de D3Dmath
  69.  
  70. static inline void vFastVectorMatrixMultiply(D3DVECTOR *vDest, D3DVECTOR *vSrc, D3DMATRIX *mat) // !!! vDest != vSrc !!!
  71. {
  72.     FLOAT w = vSrc -> x * mat -> _m._14 + vSrc -> y * mat -> _m._24 + vSrc -> z *  mat -> _m._34 + mat -> _m._44;
  73.  
  74.     vDest -> x = (vSrc -> x * mat -> _m._11 + vSrc -> y * mat -> _m._21 + vSrc -> z *  mat -> _m._31 + mat -> _m._41) / w;
  75.     vDest -> y = (vSrc -> x * mat -> _m._12 + vSrc -> y * mat -> _m._22 + vSrc -> z *  mat -> _m._32 + mat -> _m._42) / w;
  76.     vDest -> z = (vSrc -> x * mat -> _m._13 + vSrc -> y * mat -> _m._23 + vSrc -> z *  mat -> _m._33 + mat -> _m._43) / w;
  77. }
  78.  
  79. static inline void vFastNormalize(register D3DVECTOR *vDest, register D3DVECTOR *vSrc)
  80. {
  81.    register FLOAT fNorm = sqrt(vSrc -> x * vSrc -> x + vSrc -> y * vSrc -> y + vSrc -> z * vSrc -> z);
  82.    vDest -> x = vSrc -> x / fNorm;
  83.    vDest -> y = vSrc -> y / fNorm;
  84.    vDest -> z = vSrc -> z / fNorm;
  85. }
  86.  
  87. static void vRender3DEnvironment(void)
  88. {
  89.     bImage = FALSE;
  90.  
  91.     // Verrouiller le hardware 3D
  92.     if (!hW3DC_3D || !hbDBuf_3D || W3D_SUCCESS != (lError = W3D_LockHardware(hW3DC_3D)))
  93.     {
  94.          vTrace("*** E0067 : vue 3D : lock hardware (contexte @%08lX, code %ld, bm %08lX)", hW3DC_3D, lError, hbDBuf_3D);
  95.          return;
  96.     }
  97.  
  98.     // Clearer le zbuf
  99.     if (dZBuf == D3DZB_TRUE && bZBuf) W3D_ClearZBuffer(hW3DC_3D, &dZdepth);
  100.  
  101.     // Set Drawing region
  102.     sScissor.left   = (int) fLeftEdge;
  103.     sScissor.top    = (int) fTopEdge;
  104.     sScissor.width  = (int) fW;
  105.     sScissor.height = (int) fH;
  106.     W3D_SetDrawRegion(hW3DC_3D, NULL, 0, &sScissor);
  107.  
  108.     // Calculer le produit des matrices view / proj
  109.     D3DMath_MatrixMultiply(matWorld, matView, matProj);
  110.  
  111.     // Gouraud shading & zbuffer off
  112.     W3D_SetState(hW3DC_3D, W3D_GOURAUD, W3D_DISABLE);
  113.     W3D_SetState(hW3DC_3D, W3D_ZBUFFER, W3D_DISABLE);
  114.  
  115.     // Remplir le fond
  116.     WSetPen(hW3DC_3D, cBack);
  117.     WRectFill(hW3DC_3D, 0, 0, fW - 1, fH - 1);
  118.  
  119.     // Gouraud shading & zBuffer on
  120.     W3D_SetState(hW3DC_3D, W3D_GOURAUD, W3D_ENABLE);
  121.     if (dZBuf == D3DZB_TRUE && bZBuf) W3D_SetState(hW3DC_3D, W3D_ZBUFFER, W3D_ENABLE);
  122.  
  123.     // Calculer le vecteur normalisé observateur / cible (pour le lighting simpliste)
  124.     D3DVECTOR vObs = Normalize(Observer - Target);
  125.  
  126.     // Dessiner les triangles
  127.     for (register int iTriangle = 0 ; iTriangle <= iTriaLastUsed ; iTriangle++)
  128.     {
  129.         // Déréférencer le triangle
  130.         register gTri *hTri = &Triangles[iTriangle];
  131.  
  132.         // Si le triangle n'est pas enabled ou est caché alors ne rien faire
  133.         if (!hTri -> bEnabled) continue;
  134.         if (hTri -> bHidden)   continue;
  135.  
  136.         D3DVECTOR
  137.             // Déréférencer les 3 sommets du triangle
  138.             v0_UnT = Vertices[hTri -> iSommets[0]].vPoint,
  139.             v1_UnT = Vertices[hTri -> iSommets[1]].vPoint,
  140.             v2_UnT = Vertices[hTri -> iSommets[2]].vPoint,
  141.             // Transformés en coordonnées homogènes des 3 vecteurs ci-dessus
  142.             v0, v1, v2;
  143.  
  144.         // Sommets copiés pour dessiner l'outline du triangle s'il est en cours de texturage
  145.         W3D_Vertex vl0, vl1, vl2;
  146.  
  147.         // Déréférencer le material du triangle
  148.         register gMtrl *hMat = &(Materials[hTri -> iMtrl]);
  149.         D3DMATERIAL7 *hMtrl = &(hMat -> mtrl);
  150.  
  151.         // CLIPPING, step 1 : éliminer les triangles dont au moins un des sommets est trop proche de la caméra
  152.         if (    SquareMagnitude(v0_UnT - Observer) < XDC_CLIPPINGDIST
  153.              || SquareMagnitude(v1_UnT - Observer) < XDC_CLIPPINGDIST
  154.              || SquareMagnitude(v2_UnT - Observer) < XDC_CLIPPINGDIST
  155.            ) continue;
  156.  
  157.         // TRANSFORM, step 1 : Transformation coordonnées 3D vers [-0.5..+0.5] en utilisant la concaténation des matrices View et Proj
  158.         vFastVectorMatrixMultiply(&v0, &v0_UnT, &matWorld);
  159.         vFastVectorMatrixMultiply(&v1, &v1_UnT, &matWorld);
  160.         vFastVectorMatrixMultiply(&v2, &v2_UnT, &matWorld);
  161.  
  162.         // CLIPPING, step 2 : élimination des triangles en dehors du range de zbuf qu'on veut dessiner
  163.         if (    v0.z < 0.f || v0.z > 1.f
  164.              || v1.z < 0.f || v1.z > 1.f
  165.              || v2.z < 0.f || v2.z > 1.f
  166.            ) continue;
  167.  
  168.         // CLIPPING, step 3 : élimination des triangles complètement hors champ
  169.         // (le reste est laissé à Warp3D, ce qui n'est pas forcément génial)
  170.         if (    (v0.x < -0.5f && v1.x < -0.5f && v2.x < -0.5f) // complètement à gauche
  171.              || (v0.x >  0.5f && v1.x >  0.5f && v2.x >  0.5f) // complètement à droite
  172.              || (v0.y < -0.5f && v1.y < -0.5f && v2.y < -0.5f) // complètement en haut
  173.              || (v0.y >  0.5f && v1.y >  0.5f && v2.y >  0.5f) // complètement en bas
  174.            ) continue;
  175.  
  176.         // TRANSFORM, step 2 : ajustement du span X/Y dans fenêtre 3D
  177.         sTriangle.v1.x = fXMed + v0.x * fW;
  178.         sTriangle.v1.y = fYMed - v0.y * fH;
  179.         sTriangle.v2.x = fXMed + v1.x * fW;
  180.         sTriangle.v2.y = fYMed - v1.y * fH;
  181.         sTriangle.v3.x = fXMed + v2.x * fW;
  182.         sTriangle.v3.y = fYMed - v2.y * fH;
  183.         sTriangle.v1.z = v0.z;
  184.         sTriangle.v2.z = v1.z;
  185.         sTriangle.v3.z = v2.z;
  186.  
  187.         // LIGHT, step 1 : calculer les vecteurs normaux sur les trois sommets
  188.         D3DVECTOR
  189.             v01 = v1_UnT - v0_UnT,
  190.             v02 = v2_UnT - v0_UnT,
  191.             v12 = v2_UnT - v1_UnT,
  192.             vn0, vn1, vn2;
  193.  
  194.             vn0 = CrossProduct(v01, v02),
  195.             vn1 = CrossProduct(v01, v12),
  196.             vn2 = CrossProduct(v02, v12);
  197.             vFastNormalize(&vn0, &vn0),
  198.             vFastNormalize(&vn1, &vn1),
  199.             vFastNormalize(&vn2, &vn2);
  200.  
  201.         // Déréférencer les 3 couleurs à calculer
  202.         W3D_Color *c1 = &sTriangle.v1.color,
  203.                   *c2 = &sTriangle.v2.color,
  204.                   *c3 = &sTriangle.v3.color;
  205.  
  206.         // Pour l'Alpha, seule la diffuse est prise en compte, et c'est la même pour les 3 sommets
  207.         c1 -> a =
  208.         c2 -> a =
  209.         c3 -> a = hMtrl -> diffuse.a;
  210.  
  211.         // On a 2 modes de lighting :
  212.         //  A - simpliste : 1 seule lampe, à la place de la caméra ; produit avec la seule composante diffuse du matériau
  213.         if (!bLightFull)
  214.         {
  215.             // LIGHT, step 2a : Calculer les facteurs de pondération pour les 3 sommets : cos(angle vecteur regard / normale)
  216.             FLOAT
  217.                 f0 = fabs(DotProduct(vObs, vn0)),
  218.                 f1 = fabs(DotProduct(vObs, vn1)),
  219.                 f2 = fabs(DotProduct(vObs, vn2));
  220.  
  221.             // LIGHT, step 3a : moduler la couleur en fonction de la pondération calculée
  222.             FLOAT r = hMtrl -> diffuse.r,
  223.                   g = hMtrl -> diffuse.g,
  224.                   b = hMtrl -> diffuse.b;
  225.  
  226.             c1 -> r = r * f0; c1 -> g = g * f0; c1 -> b = b * f0;
  227.             c2 -> r = r * f1; c2 -> g = g * f1; c2 -> b = b * f1;
  228.             c3 -> r = r * f2; c3 -> g = g * f2; c3 -> b = b * f2;
  229.         }
  230.         else
  231.         //  B - complet : prise en compte de toutes les lampes et de toutes les composantes lampe / material
  232.         {
  233.             // LIGHT, step 2b : pré accumuler dans les RGB des 3 sommets la somme (material emissive + material ambient * ambient light)
  234.             FLOAT r0 = hMtrl -> emissive.r + hMtrl -> ambient.r  * WL_RED(cAmbient),        r1 = r0, r2 = r0,
  235.                   g0 = hMtrl -> emissive.g + hMtrl -> ambient.g  * WL_GREEN(cAmbient),      g1 = g0, g2 = g0,
  236.                   b0 = hMtrl -> emissive.b + hMtrl -> ambient.b  * WL_BLUE(cAmbient),       b1 = b0, b2 = b0;
  237.  
  238.             // LIGHT, step 3b : ajouter la contribution de chaque lampe ...
  239.             for (int iLamp = 0 ; iLamp <= iLampLastUsed ; iLamp++)
  240.             {
  241.                 // Déférérencer la lampe
  242.                 D3DLIGHT7 *hLamp = &(Lampes[iLamp].lLamp);
  243.  
  244.                 // Si la lampe n'est pas enabled ni allumée, ne rien faire
  245.                 if (!Lampes[iLamp].bEnabled) continue;
  246.                 if (!Lampes[iLamp].bLit) continue;
  247.  
  248.                 FLOAT
  249.                     // LIGHTING, step 4b : calculer les 3 pondérations : cos(lampe/sommet, normale au sommet)
  250.                     f0 = fabs(DotProduct(Normalize(v0_UnT - hLamp -> dvPosition), vn0)),
  251.                     f1 = fabs(DotProduct(Normalize(v1_UnT - hLamp -> dvPosition), vn1)),
  252.                     f2 = fabs(DotProduct(Normalize(v2_UnT - hLamp -> dvPosition), vn2)),
  253.  
  254.                     // LIGHTING, step 5b : calculer les 3 distances lampe / sommet
  255.                     d0 = Magnitude(v0_UnT - hLamp -> dvPosition),
  256.                     d1 = Magnitude(v1_UnT - hLamp -> dvPosition),
  257.                     d2 = Magnitude(v2_UnT - hLamp -> dvPosition),
  258.  
  259.                     // LIGHTING, step 6b : calculer les 3 facteurs d'atténuation polynomiale (0, 1, 2)
  260.                     a0 = 1. / (hLamp -> dvAttenuation0 + d0 * hLamp -> dvAttenuation1 + d0 * d0 * hLamp -> dvAttenuation2),
  261.                     a1 = 1. / (hLamp -> dvAttenuation0 + d1 * hLamp -> dvAttenuation1 + d1 * d1 * hLamp -> dvAttenuation2),
  262.                     a2 = 1. / (hLamp -> dvAttenuation0 + d2 * hLamp -> dvAttenuation1 + d2 * d2 * hLamp -> dvAttenuation2),
  263.  
  264.                     // LIGHTING, step 7b : calculer les contributions RGB diffuse de la lampe (lampe * material) non atténuées
  265.                     ldr = hMtrl -> diffuse.r * hLamp -> dcvDiffuse.r,
  266.                     ldg = hMtrl -> diffuse.g * hLamp -> dcvDiffuse.g,
  267.                     ldb = hMtrl -> diffuse.b * hLamp -> dcvDiffuse.b,
  268.  
  269.                     // LIGHTING, step 8b : calculer les contributions RGB ambient de la lampe (lampe * material) non atténuées
  270.                     lar = hMtrl -> ambient.r * hLamp -> dcvAmbient.r,
  271.                     lag = hMtrl -> ambient.g * hLamp -> dcvAmbient.g,
  272.                     lab = hMtrl -> ambient.b * hLamp -> dcvAmbient.b;
  273.  
  274.                 // LIGHTING, steb 9b : accumuler les contributions diffuse et ambient
  275.                 r0 += (ldr * f0 + lar) * a0;
  276.                 r1 += (ldr * f1 + lar) * a1;
  277.                 r2 += (ldr * f2 + lar) * a2;
  278.  
  279.                 g0 += (ldg * f0 + lag) * a0;
  280.                 g1 += (ldg * f1 + lag) * a1;
  281.                 g2 += (ldg * f2 + lag) * a2;
  282.  
  283.                 b0 += (ldb * f0 + lab) * a0;
  284.                 b1 += (ldb * f1 + lab) * a1;
  285.                 b2 += (ldb * f2 + lab) * a2;
  286.             }
  287.  
  288.             // LIGHTING, step 10b : caper les couleurs avec 1. (devrait être 1 mais sur Permedia 2 on retombe à noir au dessus de 0.998)
  289.             c1 -> r = min(0.998f, r0); c1 -> g = min(0.998f, g0); c1 -> b = min(0.998f, b0);
  290.             c2 -> r = min(0.998f, r1); c2 -> g = min(0.998f, g1); c2 -> b = min(0.998f, b1);
  291.             c3 -> r = min(0.998f, r2); c3 -> g = min(0.998f, g2); c3 -> b = min(0.998f, b2);
  292.         }
  293.  
  294.         // Si le triangle est celui en cours de texturage, mémoriser les sommets pour en dessiner ensuite le contour (après avoir dessiné le triangle)
  295.         if (iTriangle == iTriaHilit)
  296.         {
  297.             vl0 = sTriangle.v1;
  298.             vl1 = sTriangle.v2;
  299.             vl2 = sTriangle.v3;
  300.         }
  301.  
  302.         // Si le matériau ext texturé et que la texture est valide, régler U/V et mettre le texmapping ON
  303.         if (hMat -> bTextured && (sTriangle.tex = Textures[hMat -> iTexture].hTexture))
  304.         {
  305.             // Set Texture mapping on
  306.             W3D_SetState(hW3DC_3D, W3D_TEXMAPPING, W3D_ENABLE);
  307.  
  308.             // Affecter les u & v
  309.             sTriangle.v1.u = hTri -> u[0];  sTriangle.v1.v = hTri -> v[0];
  310.             sTriangle.v2.u = hTri -> u[1];  sTriangle.v2.v = hTri -> v[1];
  311.             sTriangle.v3.u = hTri -> u[2];  sTriangle.v3.v = hTri -> v[2];
  312.  
  313.             // Calculer les w pour la correction de perspective
  314.             sTriangle.v1.w = 1. - v0.z;
  315.             sTriangle.v2.w = 1. - v1.z;
  316.             sTriangle.v3.w = 1. - v2.z;
  317.         }
  318.  
  319.         switch(dFillMode)
  320.         {
  321.             case D3DFILL_SOLID :        // Facettes (gouraud ou texture)
  322.                W3D_DrawTriangle(hW3DC_3D, &sTriangle);
  323.                break;
  324.  
  325.             case D3DFILL_WIREFRAME :    // Fil de fer
  326.                 sLs.tex = sTriangle.tex;
  327.                 sV[0] = sV[3] = sTriangle.v1;
  328.                 sV[1] = sTriangle.v2;
  329.                 sV[2] = sTriangle.v3;
  330.                 W3D_DrawLineStrip(hW3DC_3D, &sLs);
  331.                 break;
  332.  
  333.             case D3DFILL_POINT :        // Points
  334.                 sP.tex = sTriangle.tex;
  335.                 sP.v1 = sTriangle.v1; W3D_DrawPoint(hW3DC_3D, &sP);
  336.                 sP.v1 = sTriangle.v2; W3D_DrawPoint(hW3DC_3D, &sP);
  337.                 sP.v1 = sTriangle.v3; W3D_DrawPoint(hW3DC_3D, &sP);
  338.                 break;
  339.         }
  340.  
  341.         // Set Texture mapping off
  342.         if (hMat -> bTextured && sTriangle.tex)    W3D_SetState(hW3DC_3D, W3D_TEXMAPPING, W3D_DISABLE);
  343.  
  344.         // Si le triangle est celui en cours d'édition, dessiner un contour jaune
  345.         if (iTriangle == iTriaHilit)
  346.         {
  347.             // Arrêter le zbuf et le gouraud
  348.             W3D_SetState(hW3DC_3D, W3D_GOURAUD, W3D_DISABLE);
  349.             W3D_SetState(hW3DC_3D, W3D_ZBUFFER, W3D_DISABLE);
  350.  
  351.             // Définir le jaune comme couleur flat
  352.             WSetPen(hW3DC_3D, XDC_COL_GREEN);
  353.  
  354.             // Dessiner le contour du triangle
  355.             sV[0] = sV[3] = vl0;
  356.             sV[1] = vl1;
  357.             sV[2] = vl2;
  358.             W3D_DrawLineStrip(hW3DC_3D, &sLs);
  359.  
  360.             // Remettre le gouraud et le zbuf
  361.             W3D_SetState(hW3DC_3D, W3D_GOURAUD, W3D_ENABLE);
  362.             if (dZBuf == D3DZB_TRUE && bZBuf) W3D_SetState(hW3DC_3D, W3D_ZBUFFER, W3D_ENABLE);
  363.         }
  364.     }
  365.  
  366.     // Déverrouiller le hardware 3D
  367.     W3D_UnLockHardware(hW3DC_3D);
  368.  
  369.     // Mémoriser qu'on a bien créé une image dans le double buffer
  370.     bImage = TRUE;
  371.  
  372.     // Blitter le double dans la fenêtre
  373.     vShow3DFrame();
  374. }
  375.  
  376. inline void vForce3DRefresh(BOOL bFull)
  377. {
  378.     if (!bActive) return;
  379.  
  380.     if (bFull == XDC_MODE_COMPLET)
  381.         vRender3DEnvironment();
  382.     else
  383.         vShow3DFrame();
  384. }
  385.  
  386. void vSetHints(void)
  387. {
  388.     W3D_Hint(hW3DC_3D, W3D_H_TEXMAPPING,        uHint[0]);
  389.     W3D_Hint(hW3DC_3D, W3D_H_MIPMAPPING,        uHint[1]);
  390.     W3D_Hint(hW3DC_3D, W3D_H_BILINEARFILTER,    uHint[2]);
  391.     W3D_Hint(hW3DC_3D, W3D_H_MMFILTER,          uHint[3]);
  392.     W3D_Hint(hW3DC_3D, W3D_H_PERSPECTIVE,       uHint[4]);
  393.     W3D_Hint(hW3DC_3D, W3D_H_BLENDING,          uHint[5]);
  394.     W3D_Hint(hW3DC_3D, W3D_H_FOGGING,           uHint[6]);
  395.     W3D_Hint(hW3DC_3D, W3D_H_ANTIALIASING,      uHint[7]);
  396.     W3D_Hint(hW3DC_3D, W3D_H_DITHERING,         uHint[8]);
  397.     W3D_Hint(hW3DC_3D, W3D_H_ZBUFFER,           uHint[9]);
  398. }
  399.  
  400. LRESULT CALLBACK lrPerspWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
  401. {
  402.     switch( uMsg )
  403.     {
  404.         case WM_PAINT:
  405.             // If we get WM_PAINT messages, it usually means our window was
  406.             // covered up, so we need to refresh it by re-showing the contents
  407.             // of the current frame.
  408.             vForce3DRefresh(XDC_MODE_PARTIEL);
  409.             break;
  410.  
  411.         case WM_CREATE:
  412.             InitRastPort(hdcDBuf_3D);
  413.             sTs.vertexcount = 4;
  414.             sTs.v = sV;
  415.             sLs.vertexcount = 4; sLs.v = sV; sLs.st_enable = FALSE; sLs.linewidth = 3.;
  416.             sP.tex = NULL;
  417.             sP.pointsize = 3.;
  418.  
  419.         case WM_SIZE:
  420.             vTrace("### Vue 3D : allocation double buffer / contexte Warp3D / z-buffer...");
  421.             {
  422.                 bReady = FALSE;
  423.                 // Si la taille n'a pas changé, ne rien faire
  424.                 if (iWidth == hWnd -> Width && iHeight == hWnd -> Height)
  425.                     break;
  426.                 iWidth = hWnd -> Width;
  427.                 iHeight = hWnd -> Height;
  428.  
  429.                 iLeftEdge = (int) (fLeftEdge = hWndPersp -> BorderLeft);
  430.                 iTopEdge = (int) (fTopEdge = hWndPersp -> BorderTop);
  431.                 iW = (int) (fW = hWndPersp -> Width - fLeftEdge - hWndPersp -> BorderRight);
  432.                 iH = (int) (fH = hWndPersp -> Height - fTopEdge - hWndPersp -> BorderBottom);
  433.                 fXMed = fLeftEdge + fW / 2.;
  434.                 fYMed = fTopEdge + fH / 2.;
  435.  
  436.                 // Supprimer le contexte 3D s'il est déjà alloué
  437.                 if (hW3DC_3D)
  438.                 {
  439.                     if (bZBuf)
  440.                     {
  441.                         W3D_FreeZBuffer(hW3DC_3D);
  442.                         bZBuf = FALSE;
  443.                     }
  444.                     vCloseTextures(hW3DC_3D);
  445.                     W3D_DestroyContext(hW3DC_3D);
  446.                     hW3DC_3D = NULL;
  447.                 }
  448.  
  449.                 // Supprimer le bitmap offscreen s'il est déjà alloué
  450.                 if (hbDBuf_3D)
  451.                     FreeBitMap(hbDBuf_3D);
  452.  
  453.                 // Créer le bitmap offscreen
  454.                 if (!(hbDBuf_3D = AllocBitMap(hWnd -> Width, hWnd -> Height, 8, BMF_MINPLANES | BMF_DISPLAYABLE, hWnd -> RPort -> BitMap)))
  455.                 {
  456.                     vTrace("*** E0068 : vue 3D : allocation double buffer");
  457.                     break;
  458.                 }
  459.  
  460.                 // Attacher le bitmap au rastport
  461.                 dcDBuf_3D.BitMap = hbDBuf_3D;
  462.  
  463.                 // Créer le contexte W3D
  464.                 extern ULONG lModeID, lError;
  465.                 if (!(hW3DC_3D = W3D_CreateContextTags(&lError,
  466.                     W3D_CC_MODEID,      lModeID,
  467.                     W3D_CC_BITMAP,      (ULONG) hbDBuf_3D,
  468.                     W3D_CC_YOFFSET,     0,
  469.                     W3D_CC_DRIVERTYPE,  W3D_DRIVER_BEST,
  470.                     W3D_CC_FAST,        TRUE,
  471.                     TAG_DONE)))
  472.                 {
  473.                     vTrace("*** E0069 : vue 3D : crétion contexte Warp3D (code %ld)", lError);
  474.                     FreeBitMap(hbDBuf_3D); hbDBuf_3D = NULL;
  475.                     break;
  476.                 }
  477.  
  478.                 // Charger les textures
  479.                 GenTextures(hW3DC_3D);
  480.  
  481.                 // Set alpha blending mode
  482. //                W3D_SetBlendMode(hW3DC_3D, W3D_SRC_ALPHA, W3D_ONE_MINUS_SRC_ALPHA);
  483.  
  484.                 // Hints
  485.                 vSetHints();
  486.  
  487.                 // Set states pour le contexte 3D
  488.                 W3D_SetState(hW3DC_3D, W3D_DITHERING,           W3D_ENABLE);
  489.                 W3D_SetState(hW3DC_3D, W3D_SCISSOR,             W3D_ENABLE);
  490.                 W3D_SetState(hW3DC_3D, W3D_PERSPECTIVE,         W3D_ENABLE);
  491.                 W3D_SetState(hW3DC_3D, W3D_AUTOTEXMANAGEMENT,   W3D_ENABLE);
  492.  
  493.                 W3D_SetState(hW3DC_3D, W3D_BLENDING,            W3D_DISABLE);
  494.                 W3D_SetState(hW3DC_3D, W3D_SYNCHRON,            W3D_DISABLE);
  495.                 W3D_SetState(hW3DC_3D, W3D_INDIRECT,            W3D_DISABLE);
  496.                 W3D_SetState(hW3DC_3D, W3D_TEXMAPPING,          W3D_DISABLE);
  497.                 W3D_SetState(hW3DC_3D, W3D_FOGGING,             W3D_DISABLE);
  498.                 W3D_SetState(hW3DC_3D, W3D_LOGICOP,             W3D_DISABLE);
  499.                 W3D_SetState(hW3DC_3D, W3D_STENCILBUFFER,       W3D_DISABLE);
  500.                 W3D_SetState(hW3DC_3D, W3D_DOUBLEHEIGHT,        W3D_DISABLE);
  501.  
  502.                 // Les 2 suivants n'ont pas besoin d'être réglés ici : gérés dans Render3D...()
  503. #if 0
  504.                 W3D_SetState(hW3DC_3D, W3D_GOURAUD,             W3D_DISABLE);
  505.                 W3D_SetState(hW3DC_3D, W3D_ZBUFFER,             W3D_DISABLE);
  506. #endif
  507.  
  508.                 // Allouer le ZBuffer
  509.                    if (W3D_AllocZBuffer(hW3DC_3D))
  510.                 {
  511.                     W3D_SetState(hW3DC_3D, W3D_ZBUFFERUPDATE, W3D_DISABLE);
  512.                     vTrace("*** E0047 : vue 3D : allocation ZBuffer -> pas de suppression faces cachées");
  513.                 }
  514.                 else
  515.                 {
  516.                     W3D_SetZCompareMode(hW3DC_3D, W3D_Z_LESS);
  517.                     W3D_SetState(hW3DC_3D, W3D_ZBUFFERUPDATE, W3D_ENABLE);
  518.                     bZBuf = TRUE;
  519.                     vTrace("### Vue 3D : allocation double buffer / contexte Warp3D / z-buffer OK");
  520.                 }
  521.  
  522.               
  523.                 // Redessiner la 3D dans le double buffer, Intuition va de de toute façon nous envoyer un REFRESH qui nous donnera un PAINT qui nous fera blitter le double buffer dans la fenêtre
  524.                 vRender3DEnvironment();
  525.  
  526.                 bReady = TRUE;
  527.             }
  528.             break;
  529.  
  530.         case WM_COMMAND: // Rediriger les frappes clavier et chois menus vers la fenêtre menus
  531.         case WM_CHAR :
  532.             PostMessage(hWndMenu, uMsg, wParam, lParam );
  533.             break;
  534.  
  535.         case WM_DESTROY:
  536.             // Supprimer le contexte 3D
  537.             if (hW3DC_3D)
  538.             {
  539.                 if (bZBuf)
  540.                 {
  541.                     W3D_FreeZBuffer(hW3DC_3D);
  542.                     bZBuf = FALSE;
  543.                 }
  544.                 vCloseTextures(hW3DC_3D);
  545.                 W3D_DestroyContext(hW3DC_3D);
  546.                 hW3DC_3D = NULL;
  547.             }
  548.  
  549.             // Supprimer le bitmap offscreen du double buffer
  550.             if (hbDBuf_3D) FreeBitMap(hbDBuf_3D);
  551.  
  552.             PostQuitMessage(0);
  553.             return 0L;
  554.     }
  555. #ifndef _AMIGA_
  556.     return DefWindowProc( hWnd, uMsg, wParam, lParam );
  557. #else
  558.     return 0;
  559. #endif
  560. }
  561.  
  562.